package calculadora;


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;

/**
 * CalculadoraGUI.java
 * @author Oscar Castañeda 11086 Sección 20
 * @since 16/07/2012
 * @version 2
 * Descripción: Interfaz gráfica de una calculadora en notación Post Fix, que
 *              puede realizar las operaciones de suma, resta, multiplicación y
 *              división de números flotantes.
 */
public class CalculadoraGUI extends javax.swing.JPanel {

    private Calculadora calculadora;  //Calculadora para computar.
    private boolean primerIngreso;    //True si es el primer ingreso hecho
                                      //luego de iniciar la calculadora o presionar
                                      //enter. False en caso contrario.
    
    /** Creates new form CalculadoraGUI */
    public CalculadoraGUI() {
        
        calculadora = Calculadora.instance();
        primerIngreso = true;
        
        initComponents();
        
        ListenerNum listenerNum = new ListenerNum();
        n0.addActionListener(listenerNum);
        n1.addActionListener(listenerNum);
        n2.addActionListener(listenerNum);
        n3.addActionListener(listenerNum);
        n4.addActionListener(listenerNum);
        n5.addActionListener(listenerNum);
        n6.addActionListener(listenerNum);
        n7.addActionListener(listenerNum);
        n8.addActionListener(listenerNum);
        n9.addActionListener(listenerNum);
        
        ListenerOp listenerOp = new ListenerOp();
        bOpAdd.addActionListener(listenerOp);
        bOpMinus.addActionListener(listenerOp);
        bOpMult.addActionListener(listenerOp);
        bOpDiv.addActionListener(listenerOp);
           
        ListenerSpecial listenerSpc = new ListenerSpecial();
        bBckSpc.addActionListener(listenerSpc);
        bDecimalPoint.addActionListener(listenerSpc);
        bSpace.addActionListener(listenerSpc);
        
    }

    /**
     * Permite verificar si es correspondiente limpiar la expresión en pantalla
     * y lo hace de así serlo.
     */
    private void limpiezaPantalla(){
        if (primerIngreso){
                pantalla.setText("");
                primerIngreso = !primerIngreso;
        }
    }
    
    /**
     * Clase que permite detectar y tomar una acción cuando un botón de número
     * es presionado.
     */
    private class ListenerNum implements ActionListener{

        /**
         * Detecta cuando un botón de número realiza una acción y agrega
         * a la expresión en pantalla dicho número.
         * @param e Evento de acción de un botón.
         */
        @Override
        public void actionPerformed(ActionEvent e) {
            limpiezaPantalla();
            JButton boton = (JButton) e.getSource();
            String expresionActual = pantalla.getText(); //Se agrega el número a la expresión.
            expresionActual += boton.getText();
            pantalla.setText(expresionActual);
        }
        
    }
    
    /**
     * Clase que permite detectar y tomar una acción cuando un botón de operación
     * es presionado.
     */
    private class ListenerOp implements ActionListener{

        /**
         * Detecta cuando un botón de operación realiza una acción y agrega
         * a la expresión en pantalla dicha operación.
         * @param e Evento de acción de un botón.
         */
        @Override
        public void actionPerformed(ActionEvent e) {
            limpiezaPantalla();
            JButton boton = (JButton) e.getSource();
            String expresionActual = pantalla.getText();
            expresionActual += " " + boton.getText() + " "; //Se añade el operador con espacios, 
                                                            //para evitar quedar contiguo a un número.
            pantalla.setText(expresionActual);
        }
        
    }
    
    /**
     * Clase que permite detectar y tomar una acción cuando un botón que no
     * es de número y de operación es presionado.
     */
    private class ListenerSpecial implements ActionListener{

        /**
         * Detecta cuando un botón especial realiza una acción y realiza una acción
         * según dicho botón.
         * @param e Evento de acción de un botón.
         */
        @Override
        public void actionPerformed(ActionEvent e) {
            limpiezaPantalla();
            JButton boton = (JButton) e.getSource();
            String expresionActual = pantalla.getText();
            if (boton.equals(bSpace))
                //Si el botón es el de espacio, se añade un espacio a la expresión en pantalla.
                expresionActual += " ";    
            else{
                if (boton.equals(bDecimalPoint))
                    //Si es de punto decimal, se agrega dicho punto.
                    expresionActual += ".";
                else{
                    if (boton.equals(bBckSpc)){
                        //Si se presiona el de BackSpace, se elimina el último
                        //carácter de la expresión en pantalla.
                        int index = expresionActual.length()-1;
                        if (expresionActual.endsWith(" "))
                            index -= 1;
                        if (index >= 0){
                            //Por si la expresión actual es vacía, no se hace nada.
                            expresionActual = expresionActual.substring(0, index);
                            pantalla.setText(expresionActual);
                        }
                    }
                }
            }            
            pantalla.setText(expresionActual);
        }
        
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panelBotones = new javax.swing.JPanel();
        n7 = new javax.swing.JButton();
        n8 = new javax.swing.JButton();
        n9 = new javax.swing.JButton();
        lBlank2 = new javax.swing.JLabel();
        lBlank1 = new javax.swing.JLabel();
        n4 = new javax.swing.JButton();
        n5 = new javax.swing.JButton();
        n6 = new javax.swing.JButton();
        bOpMult = new javax.swing.JButton();
        bOpDiv = new javax.swing.JButton();
        n1 = new javax.swing.JButton();
        n2 = new javax.swing.JButton();
        n3 = new javax.swing.JButton();
        bOpAdd = new javax.swing.JButton();
        bOpMinus = new javax.swing.JButton();
        n0 = new javax.swing.JButton();
        bDecimalPoint = new javax.swing.JButton();
        bSpace = new javax.swing.JButton();
        bBckSpc = new javax.swing.JButton();
        bEquals = new javax.swing.JButton();
        pantalla = new javax.swing.JLabel();
        lModelo = new javax.swing.JLabel();

        panelBotones.setLayout(new java.awt.GridLayout(4, 5, 3, 3));

        n7.setText("7");
        panelBotones.add(n7);

        n8.setText("8");
        panelBotones.add(n8);

        n9.setText("9");
        panelBotones.add(n9);
        panelBotones.add(lBlank2);
        panelBotones.add(lBlank1);

        n4.setText("4");
        panelBotones.add(n4);

        n5.setText("5");
        panelBotones.add(n5);

        n6.setText("6");
        panelBotones.add(n6);

        bOpMult.setText("*");
        panelBotones.add(bOpMult);

        bOpDiv.setText("/");
        panelBotones.add(bOpDiv);

        n1.setText("1");
        panelBotones.add(n1);

        n2.setText("2");
        panelBotones.add(n2);

        n3.setText("3");
        panelBotones.add(n3);

        bOpAdd.setText("+");
        panelBotones.add(bOpAdd);

        bOpMinus.setText("-");
        panelBotones.add(bOpMinus);

        n0.setText("0");
        panelBotones.add(n0);

        bDecimalPoint.setText(".");
        panelBotones.add(bDecimalPoint);

        bSpace.setText("SPACE");
        panelBotones.add(bSpace);

        bBckSpc.setText("<-");
        panelBotones.add(bBckSpc);

        bEquals.setText("=");
        bEquals.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bEqualsActionPerformed(evt);
            }
        });
        panelBotones.add(bEquals);

        pantalla.setBackground(new java.awt.Color(255, 255, 255));
        pantalla.setText("Calculadora Post Fix");
        pantalla.setToolTipText("");
        pantalla.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0), 2));
        pantalla.setOpaque(true);

        lModelo.setFont(new java.awt.Font("Arial", 2, 11)); // NOI18N
        lModelo.setForeground(new java.awt.Color(0, 51, 204));
        lModelo.setText("fx-BEN");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(pantalla, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE)
                    .addComponent(lModelo, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(panelBotones, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(13, 13, 13)
                .addComponent(lModelo)
                .addGap(18, 18, 18)
                .addComponent(pantalla, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(39, 39, 39)
                .addComponent(panelBotones, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Realiza el cómputo de la expresión ingresada en la calculadora al presionarse
     * el botón de igual.
     * @param evt Evento de que el botón de igual ha sido presionado.
     */
    private void bEqualsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bEqualsActionPerformed
        String resultado;
        String expPostFix = pantalla.getText();
        if (!(expPostFix.contains("ERROR")))
            resultado = calculadora.computar(expPostFix);
        else
            resultado = "";
        pantalla.setText(resultado);
        primerIngreso = true;
    }//GEN-LAST:event_bEqualsActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton bBckSpc;
    private javax.swing.JButton bDecimalPoint;
    private javax.swing.JButton bEquals;
    private javax.swing.JButton bOpAdd;
    private javax.swing.JButton bOpDiv;
    private javax.swing.JButton bOpMinus;
    private javax.swing.JButton bOpMult;
    private javax.swing.JButton bSpace;
    private javax.swing.JLabel lBlank1;
    private javax.swing.JLabel lBlank2;
    private javax.swing.JLabel lModelo;
    private javax.swing.JButton n0;
    private javax.swing.JButton n1;
    private javax.swing.JButton n2;
    private javax.swing.JButton n3;
    private javax.swing.JButton n4;
    private javax.swing.JButton n5;
    private javax.swing.JButton n6;
    private javax.swing.JButton n7;
    private javax.swing.JButton n8;
    private javax.swing.JButton n9;
    private javax.swing.JPanel panelBotones;
    private javax.swing.JLabel pantalla;
    // End of variables declaration//GEN-END:variables
}
